/*
 * my_sys.c
 *
 *  Created on: 2020年10月31日
 *      Author: tinnu
 */

#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MIMXRT1064.h"
#include "fsl_debug_console.h"
#include "fsl_semc.h"
#include "littlevgl_support.h"
#include "lv_examples/lv_exc_screen/exc_screen.h"

int16_t TabH[] = { //CRC 高位字节值表
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
		0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
		0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
uint16_t TabL[] = { //CRC 低位字节值表
		0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
		0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
		0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
		0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
		0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
		0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
		0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
		0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
		0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
		0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
		0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
		0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
		0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
		0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
		0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
		0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
		0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
		0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
		0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
		0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
		0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
		0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
		0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
		0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
		0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
		0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;


uint16_t GetCRC16(uint8_t *ptr, uint8_t len)
{
	uint16_t index;
	uint8_t crch = 0xFF; //高 CRC 字节
	uint8_t crcl = 0xFF; //低 CRC 字节

	while (len--) //计算指定长度的 CRC
	{
		index = crch ^ *ptr++;
		crch = crcl ^ TabH[index];
		crcl = TabL[index];
	}
	return ((crch<<8) | crcl);
}


void delay(void)
{
    volatile uint32_t i = 0;
    for (i = 0; i < 10000000; ++i)
    {
        __asm("NOP"); /* delay */
    }
}

void delay_ms(uint32_t n)
{
    uint32_t temp, i = 0;

#ifndef _SYSTICK_8DIV_
    SysTick->LOAD = (uint32_t)SystemCoreClock / 1000; //时间加载(SysTick->LOAD为24bit)
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
#else
    SysTick->LOAD = (uint32_t)SystemCoreClock / 8000;
    SysTick->CTRL &= (~SysTick_CTRL_CLKSOURCE_Msk);
#endif

    for (i = 0; i < n; i++)
    {
        SysTick->VAL = 0x00;                      //清空计数器
        SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开始倒数
        do
        {
            temp = SysTick->CTRL;
        } while ((temp & 0x01) && !(temp & (1 << 16))); //等待时间到达
        SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;      //关闭计数器
        SysTick->VAL = 0X00;                            //清空计数器
    }
}

#define EXAMPLE_RING_BUFFER_SIZE (150U)
static edma_tcd_t tcdMemoryPoolPtr[1];
uint8_t g_ringBuffer[EXAMPLE_RING_BUFFER_SIZE];
static uint32_t ringBufferFlag = 0U;

/* Start ring buffer. */
edma_transfer_config_t xferConfig;

void EXAMPLE_StartRingBufferEDMA(void)
{

    /* Install TCD memory for using only one TCD queue. */
    EDMA_InstallTCDMemory(&BOARD_LPUART3_RX_Handle, (edma_tcd_t *)&tcdMemoryPoolPtr[0], 1U);

    /* Prepare transfer to receive data to ring buffer. */
    EDMA_PrepareTransfer(&xferConfig,
    		(void *)(uint32_t *)LPUART_GetDataRegisterAddress(LPUART3), sizeof(uint8_t),
			g_ringBuffer, sizeof(uint8_t),
			sizeof(uint8_t),
			EXAMPLE_RING_BUFFER_SIZE,
			kEDMA_PeripheralToMemory);

    /* Submit transfer. */
    BOARD_LPUART3_RX_Handle.tcdUsed = 1U;
    BOARD_LPUART3_RX_Handle.tail    = 0U;
    EDMA_TcdReset(&BOARD_LPUART3_RX_Handle.tcdPool[0U]);
    EDMA_TcdSetTransferConfig(&BOARD_LPUART3_RX_Handle.tcdPool[0U], &xferConfig, tcdMemoryPoolPtr);

    /* Enable major interrupt for counting received bytes. */
    BOARD_LPUART3_RX_Handle.tcdPool[0U].CSR |= DMA_CSR_INTMAJOR_MASK;

    /* There is no live chain, TCD block need to be installed in TCD registers. */
    EDMA_InstallTCD(BOARD_LPUART3_RX_Handle.base, BOARD_LPUART3_RX_Handle.channel, &BOARD_LPUART3_RX_Handle.tcdPool[0U]);

    /* Start EDMA transfer. */
    EDMA_StartTransfer(&BOARD_LPUART3_RX_Handle);

    /* Enable LPUART RX EDMA. */
    LPUART_EnableRxDMA(LPUART3, true);

    /* Enable RX interrupt for detecting the IDLE line interrupt. */
    LPUART_EnableInterrupts(LPUART3, kLPUART_IdleLineInterruptEnable);
    EnableIRQ(LPUART3_IRQn);
}

uint8_t ModbusAnaly(uint8_t* i_buf, uint32_t numCounter)
{
	if(i_buf[0]!=0x01)
		return 0xFF;
	if(numCounter<5)
		return 0xFF;
	if(numCounter < i_buf[2]+5)
		return 1;
	else
	{
		if(GetCRC16(i_buf, i_buf[2]+3)==((i_buf[i_buf[2]+3]<<8)|i_buf[i_buf[2]+4]))
		{
			lvChange_pagemaingauge(i_buf[3]<<8|i_buf[4],
					i_buf[5]<<8|i_buf[6],
					i_buf[7]<<8|i_buf[8],
					i_buf[9]<<8|i_buf[10]);
		}
		return 0xFF;
	}
}

void LPUART3_IRQHandler(void)
{
    uint32_t status            = LPUART_GetStatusFlags(LPUART3);
    uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART3);

    /* If new data arrived. */
    if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) &&
        (0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts)))
    {
        (void)LPUART_ClearStatusFlags(LPUART3, kLPUART_IdleLineFlag);
        uint32_t receivedBytes      = EXAMPLE_RING_BUFFER_SIZE -
        		EDMA_GetRemainingMajorLoopCount(BOARD_LPUART3_RX_Handle.base, BOARD_LPUART3_RX_Handle.channel);



        if (receivedBytes > 130U
        		|| BOARD_LPUART3_RX_Handle.base->TCD[BOARD_LPUART3_RX_Handle.channel].CSR == 0
				|| ModbusAnaly(g_ringBuffer, receivedBytes)==0xFF)
        {
        	LPUART_EnableRxDMA(LPUART3, false);
            BOARD_LPUART3_RX_Handle.tcdUsed = 1U;
            EDMA_InstallTCD(BOARD_LPUART3_RX_Handle.base, BOARD_LPUART3_RX_Handle.channel, &BOARD_LPUART3_RX_Handle.tcdPool[0U]);
            EDMA_StartTransfer(&BOARD_LPUART3_RX_Handle);
            LPUART_EnableRxDMA(LPUART3, true);
        }
    }
    SDK_ISR_EXIT_BARRIER;
}


uint8_t g_tipString[8] = {0x01, 0x03, 0x00, 0x63, 0x00, 0x30};
static lpuart_transfer_t sendXfer={
		.data = g_tipString,
		.dataSize = 8
};

/* GPIO5_Combined_0_15_IRQn interrupt handler */
void BOARD_GPIO5_GPIO_COMB_0_15_IRQHANDLER(void) {
  /*  Place your code here */
    /* clear the interrupt status */
    GPIO_PortClearInterruptFlags(GPIO5, 1U << 0);
    /* Change state of switch. */
    GPIO_PortToggle(GPIO1, 1<<9);

    static uint8_t judge = 0;
    if(judge==0)
    	GPT_StopTimer(BOARD_GPT1_PERIPHERAL);
    else
    	GPT_StartTimer(BOARD_GPT1_PERIPHERAL);
    judge = !judge;

    while(GPIO_PinRead(GPIO5, 0)==0);
    for (int i = 0; i < 10000000; ++i)
    	__asm("NOP");
  /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
     Store immediate overlapping exception return operation might vector to incorrect interrupt. */
  #if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
  #endif
}

/* GPT1_IRQn interrupt handler */
void BOARD_GPT1_GPT_IRQHANDLER(void) {
  /*  Place your code here */
    GPT_ClearStatusFlags(BOARD_GPT1_PERIPHERAL, kGPT_OutputCompare1Flag);
    GPIO_PortToggle(GPIO1, 1<<9);

    static 	uint8_t t_counter=0;
    t_counter++;
    if(t_counter>=3){
    	uint16_t t = GetCRC16(g_tipString,6);
    	g_tipString[6] = t>>8;
    	g_tipString[7] = t&0xFF;
    	LPUART_SendEDMA(LPUART3, &BOARD_LPUART3_LPUART_eDMA_Handle, &sendXfer);
    }
    t_counter = t_counter%3;

//	GPIO_PinWrite(GPIO1, 9 , 0);
//	delay();
//	GPIO_PinWrite(GPIO1, 9 , 1);
//    GPT_ClearStatusFlags(BOARD_GPT1_PERIPHERAL, kGPT_RollOverFlag);
  /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
     Store immediate overlapping exception return operation might vector to incorrect interrupt. */
  #if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
  #endif
}


